/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fatecpg.sextociclo.implementation.repository;

import fatecpg.sextociclo.domain.entities.Client;
import fatecpg.sextociclo.domain.repository.IClientRepository;
import java.lang.reflect.Method;
import java.util.Collection;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

/**
 *
 * @author amorimjj
 */
public class ClientRepository implements IClientRepository {
    
    protected UserTransaction utx;
    protected EntityManager em;
    
    public ClientRepository(InitialContext ctx)
    {
        try {
            utx = (UserTransaction) ctx.lookup("java:comp/env/UserTransaction");
            em = (EntityManager) ctx.lookup("java:comp/env/persistence/ProjetoFatec");
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    }

    private Object execute(Method invoker, Object params[])
    {
        Object r;
        try {
            utx.begin();
            r = invoker.invoke(em, params);
            utx.commit();
        } catch (Exception e) {
            try {
                utx.rollback();
 
            } catch (SystemException ex) {
                throw new RuntimeException(ex);
            }
            throw new RuntimeException(e);
        }
        
        return r;
        
    }
    
    private Method getInvoker(Action method)
    {   
        Class parameters[] = { Object.class };
        
        if ( method == Action.find)
        {
            parameters[0] = Client.class;
            parameters[1] = Object.class;
        }
        
        try {
            return EntityManager.class.getDeclaredMethod(method.toString(), parameters);
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    private Object run(Action method, Client c)
    {
        Object params[] = { c };
        return execute(getInvoker(method), params);
    }
    
    private Object run(Action method, int clientId)
    {
        Object params[] = { Client.class, clientId };
        return execute(getInvoker(method), params);
    }
    
    @Override
    public void persist(Client c) {
        run(Action.persist, c);
    }

    @Override
    public Client merge(Client c) {
        return (Client) run(Action.merge, c);
    }

    @Override
    public Client findById(int clientId) {
        return (Client) run(Action.find, clientId);
    }

    @Override
    public void remove(Client c) {
        run(Action.erase, c);
    }

    @Override
    public Collection<Client> findAll() {
        throw new UnsupportedOperationException("Not supported yet.");
    } 
}

enum Action
{
    persist,
    merge,
    find,
    erase
}